package com.hm.base.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.hm.base.auto.SystemEnvConfigProperties;
import com.hm.base.auto.su.BeanUtil;
import com.hm.base.auto.su.R.RedisKey;
import com.hm.base.domain.SystemConfigDict;
import com.hm.base.mapper.SystemConfigDictMapper;
import com.hm.base.vo.SystemConfigDictVo;
import com.hm.common.def.DataStatusDef;
import com.hm.common.def.WhetherDef;
import com.hm.common.exception.ErrorCode;
import com.hm.common.exception.ServiceException;
import com.hm.common.su.bean.PageInfo;
import com.hm.common.su.bean.PageInfo.PageParam;
import com.hm.common.util.CommonUtil;
import com.hm.common.util.DateUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * @author shishun.wang
 * @date 上午11:02:23 2017年6月14日
 * @version 1.0
 * @describe
 */
@Slf4j
@Service
@Transactional
public class SystemConfigDictServiceImpl implements SystemConfigDictService {

	@Autowired
	private RedisTemplate<String, String> redisTemplate;

	@Autowired
	private SystemConfigDictMapper systemConfigDictMapper;

	@Autowired
	private SystemEnvConfigProperties systemEnvConfigProperties;

	@Override
	public List<SystemConfigDictVo> loadSystemConfigDictByDictType(String dictType) {
		if (CommonUtil.isEmpty(dictType)) {
			throw ServiceException.warning(ErrorCode.PARAMETERS_MISSING);
		}

		List<SystemConfigDict> dicts = systemConfigDictMapper.loadSystemConfigDictByDictType(dictType);
		if (CommonUtil.isEmpty(dicts)) {
			return new ArrayList<SystemConfigDictVo>(0);
		}
		return dicts.parallelStream().map(dict -> {
			SystemConfigDictVo vo = new SystemConfigDictVo();
			BeanUtil.copyProperties(dict, vo);

			return vo;
		}).collect(Collectors.toList());
	}

	@Override
	public SystemConfigDictVo loadSystemConfigDictByDictCode(String code) {
		if (CommonUtil.isEmpty(code)) {
			throw ServiceException.warning(ErrorCode.PARAMETERS_MISSING);
		}

		String key = RedisKey.SYSTEM_DICT_PREFIX + ":" + code.trim();
		SystemConfigDictVo value = findDictCache(key);
		if (CommonUtil.isNotEmpty(value)) {
			return value;
		}

		SystemConfigDict systemConfigDict = systemConfigDictMapper.loadSystemConfigDictByDictCode(code);
		if (CommonUtil.isEmpty(systemConfigDict)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND, code);
		}

		SystemConfigDictVo vo = new SystemConfigDictVo();
		BeanUtil.copyProperties(systemConfigDict, vo);

		this.resetDictCache(key, vo);
		return vo;
	}

	@Override
	public PageInfo<SystemConfigDictVo> query(PageParam pageParam, String dictType, String code) {
		Page<SystemConfigDict> page = PageHelper.startPage(pageParam.getPage(), pageParam.getSize(), true);
		SystemConfigDict dict = new SystemConfigDict();
		if (CommonUtil.isNotEmpty(dictType)) {
			dict.setType(dictType);
		}
		if (CommonUtil.isNotEmpty(code)) {
			dict.setCode(code);
		}
		systemConfigDictMapper.query(dict);
		if (CommonUtil.isEmpty(page.getResult())) {
			return new PageInfo<SystemConfigDictVo>(new ArrayList<SystemConfigDictVo>(0), page.getPages(), page.getTotal());
		}

		return new PageInfo<SystemConfigDictVo>(page.getResult().parallelStream().map(item -> {
			SystemConfigDictVo vo = new SystemConfigDictVo();
			BeanUtil.copyProperties(item, vo);
			vo.setCreateTime(DateUtil.data2long(item.getCreateTime()));
			vo.setSystemCfg(WhetherDef.trance(item.getSystemDefault()) == WhetherDef.YES);

			return vo;
		}).collect(Collectors.toList()), page.getPages(), page.getTotal());
	}

	private void resetDictCache(final String key, final SystemConfigDictVo value) {
		redisTemplate.opsForValue().set(key, JSONObject.toJSONString(value));
		redisTemplate.expire(key, systemEnvConfigProperties.getDictCacheLoseTime(), TimeUnit.SECONDS);
	}

	private SystemConfigDictVo findDictCache(final String key) {
		String value = redisTemplate.opsForValue().get(key);
		if (CommonUtil.isEmpty(value)) {
			return null;
		}
		return JSON.parseObject(value, SystemConfigDictVo.class);
	}

	@Override
	public void addSystemConfigDict(SystemConfigDictVo vo) {
		if (CommonUtil.isAnyEmpty(vo.getCode(), vo.getType(), vo.getSort())) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		if (CommonUtil.isNotEmpty(systemConfigDictMapper.loadSystemConfigDictByDictCode(vo.getCode()))) {
			log.error("字典code已存在");
			throw ServiceException.warning(ErrorCode.DATA_EXISTING);
		}

		SystemConfigDict systemConfigDict = new SystemConfigDict();
		BeanUtil.copyProperties(vo, systemConfigDict);
		systemConfigDict.setId(null);
		systemConfigDict.setCreateTime(new Date());
		systemConfigDict.setStatus(DataStatusDef.ENABLE.name());
		systemConfigDict.setSystemDefault(WhetherDef.NO.name());

		systemConfigDictMapper.insert(systemConfigDict);
	}

	@Override
	public void updateSystemConfigDict(SystemConfigDictVo vo) {
		if (CommonUtil.isAnyEmpty(vo.getId(), vo.getCode(), vo.getType(), vo.getSort())) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		SystemConfigDict configDict = systemConfigDictMapper.loadSystemConfigDictByDictCode(vo.getCode());
		if (CommonUtil.isNotEmpty(configDict) && configDict.getId() != vo.getId()) {
			log.error("字典code已存在");
			throw ServiceException.warning(ErrorCode.DATA_EXISTING);
		}

		configDict = systemConfigDictMapper.selectByPrimaryKey(vo.getId());
		if (CommonUtil.isEmpty(configDict)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND);
		}

		if (WhetherDef.trance(configDict.getSystemDefault()) == WhetherDef.YES) {
			throw ServiceException.warning(ErrorCode.NO_DATA_ACCESS);
		}

		configDict.setType(vo.getType());
		configDict.setCode(vo.getCode());
		configDict.setName(vo.getName());
		configDict.setNote(vo.getNote());
		configDict.setSort(vo.getSort());

		systemConfigDictMapper.updateByPrimaryKey(configDict);
	}

	@Override
	public void deleteSystemConfigDict(List<Long> dictIds) {
		if (CommonUtil.isEmpty(dictIds)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		dictIds.parallelStream().forEach(item -> {
			SystemConfigDict systemConfigDict = systemConfigDictMapper.selectByPrimaryKey(item);
			if (CommonUtil.isEmpty(systemConfigDict)) {
				throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND);
			}

			if (WhetherDef.trance(systemConfigDict.getSystemDefault()) == WhetherDef.NO) {
				systemConfigDict.setStatus(DataStatusDef.DISABLE.name());
				systemConfigDictMapper.updateByPrimaryKey(systemConfigDict);
			}

		});
	}

	@Override
	public SystemConfigDictVo getSystemConfigDict(Long dictId) {
		if (CommonUtil.isEmpty(dictId)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		SystemConfigDict systemConfigDict = systemConfigDictMapper.selectByPrimaryKey(dictId);
		if (CommonUtil.isEmpty(systemConfigDict)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND);
		}

		SystemConfigDictVo vo = new SystemConfigDictVo();
		BeanUtil.copyProperties(systemConfigDict, vo);

		return vo;
	}
}
